package com.mlk.bet.service.impl;

import cn.hutool.core.util.IdUtil;
import com.mlk.bet.mapper.EngBetMapper;
import com.mlk.bet.po.EngBet;
import com.mlk.bet.service.BetService;
import com.mlk.constant.EngConstant;
import com.mlk.core.component.page.Page;
import com.mlk.core.component.page.Pager;
import com.mlk.core.exception.GlobalException;
import com.mlk.core.util.ServerResponse;
import com.mlk.engSystem.constant.SystemParam;
import com.mlk.engSystem.service.EngSysParamService;
import com.mlk.engUser.mapper.EngUserMapper;
import com.mlk.engUser.po.EngUser;
import com.mlk.score.mapper.EngInScoreMapper;
import com.mlk.score.mapper.EngOutScoreMapper;
import com.mlk.score.po.EngInScore;
import com.mlk.score.po.EngOutScore;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.IntStream;

@Service
public class BetServiceImpl implements BetService {

    /**
     * 抽奖集合的名称
     */
    public static final String BET_SET_PREFIX = "bet_set";

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Resource
    private EngBetMapper engBetMapper;

    @Resource
    private EngSysParamService engSysParamService;

    @Resource
    private EngOutScoreMapper engOutScoreMapper;

    @Resource
    private EngUserMapper engUserMapper;

    @Resource
    private EngInScoreMapper engInScoreMapper;


    @Override
    public ServerResponse getBetScore() {
        return ServerResponse.ok(this.engSysParamService.getIntValue(SystemParam.BET_OF_SCORE));
    }

    /**
     * 获取抽奖的内容信息
     * @return
     */
    @Override
    public ServerResponse getBetContent() {
        return ServerResponse.ok(this.engBetMapper.selectList(null));
    }

    /**
     * 判断用户是否能抽奖
     * @param openId
     * @return
     */
    @Override
    public ServerResponse checkOwnScore(String openId) {
        // 获取用户信息
        EngUser user = this.engUserMapper.selectOne(EngUser.builder().openId(openId).build());
        // 获取抽奖的积分限制
        int score = this.engSysParamService.getIntValue(SystemParam.BET_OF_SCORE);
        if(score > user.getScore()){
            return ServerResponse.fail("用户的积分余额不足");
        }
        return ServerResponse.ok("可以进行抽奖");
    }


    private String getBetSetPrefix(){
        return IdUtil.fastSimpleUUID();
    }

    @Override
    public void refreshRedisCache() {
        List<EngBet> betList = this.engBetMapper.selectList(null);

        // 删除之前的redis的数据
        redisTemplate.delete(BET_SET_PREFIX);
        // 向集合之中添加数据
        betList.stream().forEach(e->{
            int count = e.getRate();
            IntStream.range(0,count).forEach(item->{
                // 添加数据
                redisTemplate.opsForSet().add(BET_SET_PREFIX,getBetSetPrefix()+"-"+e.getAmount());
            });
        });



    }


    /**
     * 获取分页数据
     * @return
     */
    @Page
    @Override
    public Pager listPage() {
        return Pager.adapt(this.engBetMapper.selectList(null));
    }

    /**
     * 更新数据内容
     * @param betPo
     * @return
     */
    @Override
    @Transactional
    public ServerResponse update(EngBet betPo) {

        int count = this.engBetMapper.updateById(betPo);
        if(count == 0){
            throw new GlobalException("更新成功");
        }

        this.refreshRedisCache();
        return ServerResponse.ok("操作成功");
    }

    /**
     * 积分抽奖
     * @param openId
     * @return
     */
    @Override
    @Transactional
    public ServerResponse bet(String openId) {
        // 获取用户信息
        EngUser user = this.engUserMapper.selectOne(EngUser.builder().openId(openId).build());
        // 获取抽奖的积分限制
        int score = this.engSysParamService.getIntValue(SystemParam.BET_OF_SCORE);
        if(score > user.getScore()){
            return ServerResponse.fail("用户的积分余额不足");
        }

        // 下面进行抽奖的逻辑
        Object result = redisTemplate.opsForSet().randomMember(BET_SET_PREFIX);
        // 实际上我们存储的就是一个String
        String value = null;
        if(result instanceof String){
            value = (String) result;
            value = StringUtils.split(value,"-")[1];
        }

        // 减去用户的积分信息
        int count = this.engUserMapper.addUserScore(openId,(-1)*score);
        if(count == 0){
            throw new GlobalException("抽奖失败");
        }

        // 增加一个用户的积分支出的途径
        EngOutScore outScore = new EngOutScore();
        outScore.setOpenId(openId);
        outScore.setType(EngConstant.OUT_SCORE_TARGET.BET_SCORE);
        outScore.setCreateTime(new Date());
        outScore.setNum(score);
        count = this.engOutScoreMapper.insert(outScore);
        if(count == 0){
            throw new GlobalException("抽奖失败");
        }

        // 补充 ；； 需要对用户增加积分信息
        if(Integer.parseInt(value) > 0 ){
            // 增加用户的积分信息
            count = this.engUserMapper.addUserScore(openId,Integer.parseInt(value));
            if(count == 0){
                throw new GlobalException("抽奖失败");
            }

            // 增加积分进项
            EngInScore inScore = new EngInScore();
            inScore.setOpenId(openId);
            inScore.setType(EngConstant.IN_SCORE_SOURCE.BET_SOCRE);
            inScore.setCreateTime(new Date());
            inScore.setNum(Integer.parseInt(value));
            count = this.engInScoreMapper.insert(inScore);
            if(count == 0){
                throw new GlobalException("抽奖失败");
            }
        }
        return ServerResponse.ok("抽奖成功",value);
    }
}
